package com.ssm.basis.service.util;

import com.ssm.basis.service.exception.CustomException;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;

public abstract class KeyPairUtil {
    /**
     * 从 classpath 下获取 RSA 秘钥对，windows cmd 换行符：^
     * * JKS
     * keytool -genkeypair -alias jhxxb -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 \
     * -keystore jhxxb.jks -keypass keypass -storepass storepass \
     * -dname "CN=jhxxb.com, OU=yf, O=xiaomi, L=wuhan, ST=hubei, C=CN"
     * * PKCS12
     * keytool -genkeypair -alias jhxxb -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 \
     * -keystore jhxxb.p12 -storetype PKCS12 -storepass storepass \
     * -dname "CN=jhxxb.com, OU=yf, O=xiaomi, L=wuhan, ST=hubei, C=CN"
     */
    public static KeyPair loadKeyPairFromKeyStore(String keyStoreFile, String storePassword, String keyPassword,
                                                  String keyAlias, String type) {
        if (type == null) {
            String ext = StringUtils.getFilenameExtension(keyStoreFile);
            type = ext == null ? KeyStore.getDefaultType() : ext;
        }

        // 加载文件
        try (InputStream is = new ClassPathResource(keyStoreFile).getInputStream()) {
            KeyStore keyStore = KeyStore.getInstance(type);

            // InputStream is = Files.newInputStream(Paths.get(keyStoreFile))
            // @Cleanup InputStream is = new FileInputStream(ResourceUtils.getFile(keyStoreFile));
            keyStore.load(is, storePassword.toCharArray());

            // 获取私钥
            // PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyPassword.toCharArray());
            RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyStore.getKey(keyAlias, keyPassword.toCharArray());
            if (privateKey == null) {
                throw new RuntimeException("Couldn't load key with alias '" + keyAlias + "' from keystore");
            }

            // 获取公钥
            PublicKey publicKey;
            Certificate certificate = keyStore.getCertificate(keyAlias);
            if (certificate != null) {
                publicKey = certificate.getPublicKey();
            } else {
                RSAPublicKeySpec spec = new RSAPublicKeySpec(privateKey.getModulus(), privateKey.getPublicExponent());
                publicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
            }

            return new KeyPair(publicKey, privateKey);
        } catch (UnrecoverableKeyException | InvalidKeySpecException | NoSuchAlgorithmException |
                 IOException | KeyStoreException | CertificateException e) {
            throw new CustomException(e);
        }
    }
}